﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Reflection;

namespace PickGold
{
	/// <summary/>
	[Serializable, ComVisible(true)]
	public class SerialReader : Stream
	{
		#region inner class

		class ReadState
		{
			/// <summary>
			/// 回车标识
			/// </summary>
			public int cr;
			/// <summary>
			/// 换行标识
			/// </summary>
			public int lf;
			/// <summary>
			/// 新行标识
			/// </summary>
			public int nl;
			/// <summary>
			/// 最大限制
			/// </summary>
			public int ml;
			public int ct;
			public int bp;
			public byte[] bs;
			public char[] cs;
			public string se;
			public StringBuilder vs;
			public AsyncResultWrap rw;
		}

		#endregion

		internal int LastRead;
		internal bool Closable;
		internal byte[] ByteBuffer;
		internal int ByteLength;
		internal int BytePosition;
		internal char[] CharBuffer;
		internal StringBuilder InnerBuffer;
		internal Encoding InnerEncoding;
		internal Stream InnerStream;

		internal SerialReader() { }

		/// <summary/>
		public SerialReader(Stream stream) : this(stream, null, 0, true) { }

		/// <summary/>
		public SerialReader(Stream stream, Encoding encoding) : this(stream, encoding, 0, true) { }

		/// <summary/>
		public SerialReader(Stream stream, Encoding encoding, int bufferSize) : this(stream, encoding, 0, true) { }

		/// <summary/>
		public SerialReader(Stream stream, Encoding encoding, int bufferSize, bool closable)
		{
			if ((stream == null) || (encoding == null))
				throw new ArgumentNullException(MethodBase.GetCurrentMethod().GetParameters()[0].Name);

			if (!stream.CanRead)
				throw new ArgumentException("Stream Not Readable");

			this.InnerStream = stream;
			if (encoding == null)
				encoding = Encoding.UTF8;
			this.InnerEncoding = encoding;
			if (bufferSize <= 0)
				bufferSize = BitUtil.K;
			else if (bufferSize <= byte.MaxValue)
				bufferSize = byte.MaxValue + 1;
			this.ByteBuffer = new byte[bufferSize];
			this.ByteLength = 0;
			this.BytePosition = 0;
			this.Closable = closable;
			this.LastRead = 1;
		}

		/// <summary/>
		protected override void Dispose(bool disposing)
		{
			try
			{
				if (this.Closable && disposing && this.InnerStream != null)
					this.InnerStream.Close();
			}
			finally
			{
				this.InnerStream = null;
				this.InnerEncoding = null;
				this.ByteBuffer = null;
				this.CharBuffer = null;
				this.InnerBuffer = null;
			}
			base.Dispose(disposing);
		}

		private int ReadBuffer(bool move = false)
		{
			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			if (this.ByteBuffer.Length > this.ByteLength)
			{
				this.LastRead = this.InnerStream.Read(this.ByteBuffer, this.ByteLength, this.ByteBuffer.Length);
				this.ByteLength += this.LastRead;
				return this.LastRead;
			}

			if (this.ByteLength > this.BytePosition)
			{
				if (!move)
					throw new ArgumentOutOfRangeException("有剩余数据必须移动处理，请传入移动剩余数据参数为 True 值！");

				var bs = new byte[this.ByteLength - this.BytePosition];
				Buffer.BlockCopy(this.ByteBuffer, this.BytePosition, bs, 0, this.ByteLength - this.BytePosition);
				Buffer.BlockCopy(bs, 0, this.ByteBuffer, 0, this.ByteLength - this.BytePosition);
				this.BytePosition = 0;
			}
			this.LastRead = this.InnerStream.Read(this.ByteBuffer, 0, this.ByteBuffer.Length);
			this.ByteLength = this.LastRead;
			return this.LastRead;
		}

		private IAsyncResult BeginReadBuffer(bool move, AsyncCallback callback, object state)
		{
			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			if (this.ByteBuffer.Length > this.ByteLength)
				return this.InnerStream.BeginRead(this.ByteBuffer, this.ByteLength, this.ByteBuffer.Length, callback, state);

			if (this.ByteLength > this.BytePosition)
			{
				if (!move)
					throw new ArgumentOutOfRangeException("有剩余数据必须移动处理，请传入移动剩余数据参数 move 为 True 值！");

				var bs = new byte[this.ByteLength - this.BytePosition];
				Buffer.BlockCopy(this.ByteBuffer, this.BytePosition, bs, 0, this.ByteLength - this.BytePosition);
				Buffer.BlockCopy(bs, 0, this.ByteBuffer, 0, this.ByteLength - this.BytePosition);
				this.BytePosition = 0;
			}
			this.ByteLength = 0;
			return this.InnerStream.BeginRead(this.ByteBuffer, 0, this.ByteBuffer.Length, callback, state);
		}

		/// <summary/>
		public int ReadChars([In, Out] char[] buffer)
		{
			if (buffer == null)
				return 0;

			return this.ReadChars(buffer, 0);
		}

		/// <summary/>
		public IAsyncResult BeginReadChars([In, Out] char[] buffer, AsyncCallback callback, object state)
		{
			if (buffer == null)
				return AsyncResultWrap.SyncComplete(0, null, callback, state);

			return this.BeginReadChars(buffer, 0, callback, state);
		}

		/// <summary/>
		public int ReadChars([In, Out] char[] buffer, int index)
		{
			if (buffer == null)
				return 0;

			if (this.BytePosition >= this.ByteLength && this.ReadBuffer() == 0)
				return 0;

			var i = this.InnerEncoding.GetChars(this.ByteBuffer, this.BytePosition, this.ByteLength - this.BytePosition, buffer, index);
			this.BytePosition += this.InnerEncoding.GetByteCount(buffer, index, i);
			return i;
		}

		/// <summary/>
		public IAsyncResult BeginReadChars([In, Out] char[] buffer, int index, AsyncCallback callback, object state)
		{
			if (buffer == null)
				return AsyncResultWrap.SyncComplete(0, null, callback, state);

			var i = this.ByteLength - this.BytePosition;
			try
			{
				if (i <= 0)
				{
					var ar = new AsyncResultWrap(1, callback, state);
					ar.WrapResult = this.BeginReadBuffer(false, this.InnerReadChars, new object[] { ar, buffer, index, });
					return ar;
				}

				i = this.InnerEncoding.GetChars(this.ByteBuffer, this.BytePosition, i, buffer, index);
				if (i == 0)
				{
					var ar = new AsyncResultWrap(1, callback, state);
					ar.WrapResult = this.BeginReadBuffer(true, this.InnerReadChars, new object[] { ar, buffer, index, });
					return ar;
				}
			}
			catch (Exception x)
			{
				return AsyncResultWrap.SyncComplete(x,  callback, state);
			}

			this.BytePosition += this.InnerEncoding.GetByteCount(buffer, index, i);
			return AsyncResultWrap.SyncComplete(i, null, callback, state);
		}

		private void InnerReadChars(IAsyncResult result)
		{
			var os = result.AsyncState as object[];
			var ar = os[0] as AsyncResultWrap;
			ar.WrapResult = result;
			if (this.BytePosition >= this.ByteLength)
			{
				ar.Complete(0, null);
				return;
			}

			var cs = os[1] as char[];
			var ci = (int)os[2];
			this.LastRead = this.InnerStream.EndRead(result);
			this.ByteLength += this.LastRead;
			var i = this.InnerEncoding.GetChars(this.ByteBuffer, this.BytePosition, this.ByteLength - this.BytePosition, cs, ci);
			this.BytePosition += this.InnerEncoding.GetByteCount(cs, ci, i);
			ar.Complete(i, null);
		}

		/// <summary/>
		public int EndReadChars(IAsyncResult asyncResult)
		{
			var ar = asyncResult as IAsyncResultWrap;
			if (ar.WrapError != null)
				throw ar.WrapError;

			return (int)ar.WrapReturn;
		}

		/// <summary>
		/// 读取行，行尾带换行符，若为流结尾则不一定带换行符，如果超过最大数据则返回 Null
		/// </summary>
		/// <param name="max">返回最大字符数，小于零表示不限制</param>
		/// <returns>返回行，行尾带换行符，若为流结尾则不一定带换行符，如果超过最大数据则返回 Null</returns>
		public string ReadLine(int max)
		{
			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			if (max == 0)
				return string.Empty;

			var rs = new ReadState();
			rs.cr = 0;//回车标识
			rs.lf = 0;//换行标识
			rs.ct = 0;
			rs.bs = this.ByteBuffer;
			rs.bp = this.BytePosition;
			rs.vs = this.InnerBuffer;
			rs.ml = max;
			rs.nl = rs.ml > 0 ? (rs.ml > BitUtil.K ? BitUtil.K : rs.ml) : BitUtil.K;//主作用：新行标识
			rs.cs = this.CharBuffer;
			if (rs.cs == null || rs.cs.Length < rs.nl)
				this.CharBuffer = rs.cs = new char[rs.nl];
			rs.nl = this.InnerEncoding.GetMaxByteCount(rs.cs.Length);
			if (rs.nl % BitUtil.K > 0)
				rs.nl = BitUtil.K * (rs.nl / BitUtil.K + 1);
			if (this.InnerBuffer == null)
				this.InnerBuffer = rs.vs = new StringBuilder();
			else
				this.InnerBuffer.Clear();
			if (rs.nl > this.ByteBuffer.Length - this.BytePosition)
			{
				this.ByteBuffer = new byte[rs.nl > this.ByteBuffer.Length ? rs.nl : this.ByteBuffer.Length];
				this.ByteLength -= this.BytePosition;
				Buffer.BlockCopy(rs.bs, this.BytePosition, this.ByteBuffer, 0, this.ByteLength);
				this.BytePosition = 0;
				rs.bs = this.ByteBuffer;
				rs.bp = this.BytePosition;
			}
			rs.nl = 0;
			for (; ; )
			{
				if (this.ByteLength <= this.BytePosition && this.ReadBuffer() == 0)
				{
					if (rs.nl > 0)
					{
						rs.nl = rs.ct - rs.nl;
						this.BytePosition = rs.bp - this.InnerEncoding.GetByteCount(rs.cs, rs.ct - rs.nl, rs.nl);
						this.Dispose();
						return rs.vs.ToString().Remove(rs.vs.Length - rs.nl);
					}

					return string.Empty;
				}

				rs.ct = this.InnerEncoding.GetChars(rs.bs, rs.bp, this.ByteLength - rs.bp, rs.cs, 0);
				if (rs.ct == 0)
					continue;

				rs.vs.Append(rs.cs, 0, rs.ct);
				rs.bp += this.InnerEncoding.GetByteCount(rs.cs, 0, rs.ct);
				for (rs.nl = 0; rs.nl < rs.ct; rs.nl++)
				{
					switch (rs.cs[rs.nl])
					{
						case '\r':
							rs.cr++;
							break;
						case '\n':
							rs.lf++;
							break;
					}
					if (rs.lf > 0 || rs.cr > 1)
						break;
				}
				if (rs.lf > 0 || rs.cr > 1)
				{
					rs.nl = rs.ct - rs.nl;
					this.BytePosition = rs.bp - this.InnerEncoding.GetByteCount(rs.cs, rs.ct - rs.nl, rs.nl);
					return rs.vs.ToString().Remove(rs.vs.Length - rs.nl);
				}

				if (rs.ml >= 0 && rs.vs.Length >= rs.ml)
					break;

				if (rs.cr == 0)
					rs.nl = 0;
			}
			//this._BytePosition = bp;
			//return vs.ToString();
			if (rs.nl > 0)
			{
				rs.nl = rs.ct - rs.nl;
				this.BytePosition = rs.bp - this.InnerEncoding.GetByteCount(rs.cs, rs.ct - rs.nl, rs.nl);
				return rs.vs.ToString().Remove(rs.vs.Length - rs.nl);
			}

			return null;
		}

		/// <summary>
		/// 读取行，行尾带换行符，若为流结尾则不一定带换行符，如果超过最大数据则返回 Null
		/// </summary>
		/// <param name="max">返回最大字符数，小于零表示不限制</param>
		/// <param name="callback"></param>
		/// <param name="state"></param>
		/// <returns></returns>
		public IAsyncResult BeginReadLine(int max, AsyncCallback callback, object state)
		{
			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			if (max == 0)
				return AsyncResultWrap.SyncComplete(string.Empty, null, callback, state);

			var rs = new ReadState();
			rs.rw = new AsyncResultWrap(-1, callback, state);
			rs.cr = 0;//回车标识
			rs.lf = 0;//换行标识
			rs.ct = 0;
			rs.bs = this.ByteBuffer;
			rs.bp = this.BytePosition;
			rs.vs = this.InnerBuffer;
			rs.ml = max;
			rs.nl = rs.ml > 0 ? (rs.ml > BitUtil.K ? BitUtil.K : rs.ml) : BitUtil.K;//主作用：新行标识
			rs.cs = this.CharBuffer;
			if (rs.cs == null || rs.cs.Length < rs.nl)
				this.CharBuffer = rs.cs = new char[rs.nl];
			rs.nl = this.InnerEncoding.GetMaxByteCount(rs.cs.Length);
			if (rs.nl % BitUtil.K > 0)
				rs.nl = BitUtil.K * (rs.nl / BitUtil.K + 1);
			if (this.InnerBuffer == null)
				this.InnerBuffer = rs.vs = new StringBuilder();
			else
				this.InnerBuffer.Clear();
			if (rs.nl > this.ByteBuffer.Length - this.BytePosition)
			{
				this.ByteBuffer = new byte[rs.nl > this.ByteBuffer.Length ? rs.nl : this.ByteBuffer.Length];
				this.ByteLength -= this.BytePosition;
				Buffer.BlockCopy(rs.bs, this.BytePosition, this.ByteBuffer, 0, this.ByteLength);
				this.BytePosition = 0;
				rs.bs = this.ByteBuffer;
				rs.bp = this.BytePosition;
			}
			rs.nl = 0;
			rs.rw.WrapTag = rs;
			if (this.BytePosition >= this.ByteLength)
				rs.rw.WrapResult = this.BeginReadBuffer(false, this.InnerReadLine, rs);
			else
				this.InnerReadLine(rs.rw);
			return rs.rw;
		}

		private void InnerReadLine(IAsyncResult result)
		{
			var rs = result.AsyncState as ReadState;
			if (rs == null)
			{
				var ar = result as IAsyncResultWrap;
				rs = ar.WrapTag as ReadState;
			}
			else
			{
				try
				{
					this.LastRead = this.InnerStream.EndRead(result);
				}
				catch (Exception x)
				{
					rs.rw.Complete(x);
					return;
				}

				if (this.LastRead == 0)
				{
					if (rs.nl > 0)
					{
						rs.nl = rs.ct - rs.nl;
						this.BytePosition = rs.bp - this.InnerEncoding.GetByteCount(rs.cs, rs.ct - rs.nl, rs.nl);
						this.Dispose();
						rs.rw.Complete(rs.vs.ToString().Remove(rs.vs.Length - rs.nl), null);
						return;
					}

					rs.rw.Complete(string.Empty, null);
					return;
				}

				this.ByteLength += this.LastRead;
			}

			rs.ct = this.InnerEncoding.GetChars(rs.bs, rs.bp, this.ByteLength - rs.bp, rs.cs, 0);
			if (rs.ct == 0)
			{
				rs.rw.WrapResult = this.BeginReadBuffer(false, this.InnerReadLine, rs);
				return;
			}

			rs.vs.Append(rs.cs, 0, rs.ct);
			rs.bp += this.InnerEncoding.GetByteCount(rs.cs, 0, rs.ct);
			for (rs.nl = 0; rs.nl < rs.ct; rs.nl++)
			{
				switch (rs.cs[rs.nl])
				{
					case '\r':
						rs.cr++;
						break;
					case '\n':
						rs.lf++;
						break;
				}
				if (rs.lf > 0 || rs.cr > 1)
					break;
			}
			if (rs.lf > 0 || rs.cr > 1)
			{
				rs.nl = rs.ct - rs.nl;
				this.BytePosition = rs.bp - this.InnerEncoding.GetByteCount(rs.cs, rs.ct - rs.nl, rs.nl);
				rs.rw.Complete(rs.vs.ToString().Remove(rs.vs.Length - rs.nl), null);
				return;
			}

			if (rs.ml >= 0 && rs.vs.Length >= rs.ml)
			{
				if (rs.nl > 0)
				{
					rs.nl = rs.ct - rs.nl;
					this.BytePosition = rs.bp - this.InnerEncoding.GetByteCount(rs.cs, rs.ct - rs.nl, rs.nl);
					rs.rw.Complete(rs.vs.ToString().Remove(rs.vs.Length - rs.nl), null);
					return;
				}

				//this._BytePosition = bp;
				//rs.rw.Complete(rs.vs.ToString(), null);
				rs.rw.Complete(null, null);
				return;
			}

			if (rs.cr == 0)
				rs.nl = 0;
			rs.rw.WrapResult = this.BeginReadBuffer(false, this.InnerReadLine, rs);
		}

		/// <summary/>
		public string EndReadLine(IAsyncResult asyncResult)
		{
			var ar = asyncResult as IAsyncResultWrap;
			if (ar.WrapError != null)
				throw ar.WrapError;

			return (string)ar.WrapReturn;
		}

		/// <summary>
		/// 读取到流结束的文本，如果超过最大数据则返回 Null
		/// </summary>
		/// <param name="max">返回最大字符数，小于零表示不限制</param>
		/// <returns>返回到流结束文本，如果超过最大数据则返回 Null</returns>
		public string ReadToEnd(int max)
		{
			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			if (max == 0)
				return string.Empty;

			var rs = new ReadState();
			rs.vs = this.InnerBuffer;
			rs.bs = this.ByteBuffer;
			rs.ml = max;
			rs.bp = rs.ml > 0 ? (rs.ml > BitUtil.K ? BitUtil.K : rs.ml) : BitUtil.K;
			rs.cs = this.CharBuffer;
			if (rs.cs == null || rs.cs.Length < rs.bp)
				this.CharBuffer = rs.cs = new char[rs.bp];
			rs.bp = this.InnerEncoding.GetMaxByteCount(rs.cs.Length);
			if (rs.bp % BitUtil.K > 0)
				rs.bp = BitUtil.K * (rs.bp / BitUtil.K + 1);
			if (this.InnerBuffer == null)
				this.InnerBuffer = rs.vs = new StringBuilder();
			else
				this.InnerBuffer.Clear();
			if (rs.bp > this.ByteBuffer.Length - this.BytePosition)
			{
				this.ByteBuffer = new byte[rs.bp > this.ByteBuffer.Length ? rs.bp : this.ByteBuffer.Length];
				this.ByteLength -= this.BytePosition;
				Buffer.BlockCopy(rs.bs, this.BytePosition, this.ByteBuffer, 0, this.ByteLength);
				this.BytePosition = 0;
				rs.bs = this.ByteBuffer;
			}
			rs.bp = this.BytePosition;
			for (; ; )
			{
				if (this.ByteLength <= this.BytePosition && this.ReadBuffer() == 0)
				{
					this.BytePosition = rs.bp;
					this.Dispose();
					return rs.vs.ToString();
				}

				var ct = this.InnerEncoding.GetChars(rs.bs, rs.bp, this.ByteLength - rs.bp, rs.cs, 0);
				if (ct == 0)
					continue;

				rs.vs.Append(rs.cs, 0, ct);
				rs.bp += this.InnerEncoding.GetByteCount(rs.cs, 0, ct);
				if (max >= 0 && rs.vs.Length >= max)
					break;
			}
			//this._BytePosition = bp;
			//return vs.ToString();
			return null;
		}

		/// <summary>
		/// 读取到流结束的文本，如果超过最大数据则返回 Null
		/// </summary>
		/// <param name="max">返回最大字符数，小于零表示不限制</param>
		/// <param name="callback"></param>
		/// <param name="state"></param>
		/// <returns></returns>
		public IAsyncResult BeginReadToEnd(int max, AsyncCallback callback, object state)
		{
			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			if (max == 0)
				return AsyncResultWrap.SyncComplete(string.Empty, null, callback, state);

			var rs = new ReadState();
			rs.rw = new AsyncResultWrap(-1, callback, state);
			rs.vs = this.InnerBuffer;
			rs.bs = this.ByteBuffer;
			rs.ml = max;
			rs.bp = rs.ml > 0 ? (rs.ml > BitUtil.K ? BitUtil.K : rs.ml) : BitUtil.K;
			rs.cs = this.CharBuffer;
			if (rs.cs == null || rs.cs.Length < rs.bp)
				this.CharBuffer = rs.cs = new char[rs.bp];
			rs.bp = this.InnerEncoding.GetMaxByteCount(rs.cs.Length);
			if (rs.bp % BitUtil.K > 0)
				rs.bp = BitUtil.K * (rs.bp / BitUtil.K + 1);
			if (this.InnerBuffer == null)
				this.InnerBuffer = rs.vs = new StringBuilder();
			else
				this.InnerBuffer.Clear();
			if (rs.bp > this.ByteBuffer.Length - this.BytePosition)
			{
				this.ByteBuffer = new byte[rs.bp > this.ByteBuffer.Length ? rs.bp : this.ByteBuffer.Length];
				this.ByteLength -= this.BytePosition;
				Buffer.BlockCopy(rs.bs, this.BytePosition, this.ByteBuffer, 0, this.ByteLength);
				this.BytePosition = 0;
				rs.bs = this.ByteBuffer;
			}
			rs.bp = this.BytePosition;
			if (this.BytePosition >= this.ByteLength)
				rs.rw.WrapResult = this.BeginReadBuffer(false, this.InnerReadToEnd, rs);
			else
				this.InnerReadToEnd(rs.rw);
			return rs.rw;
		}

		private void InnerReadToEnd(IAsyncResult result)
		{
			var rs = result.AsyncState as ReadState;
			if (rs == null)
			{
				var ar = result as IAsyncResultWrap;
				rs = ar.WrapTag as ReadState;
			}
			else
			{
				try
				{
					this.LastRead = this.InnerStream.EndRead(result);
				}
				catch (Exception x)
				{
					rs.rw.Complete(x);
					return;
				}

				if (this.LastRead == 0)
				{
					this.BytePosition = rs.bp;
					this.Dispose();
					rs.rw.Complete(rs.vs.ToString(), null);
					return;
				}

				this.ByteLength += this.LastRead;
			}

			var ct = this.InnerEncoding.GetChars(rs.bs, rs.bp, this.ByteLength - rs.bp, rs.cs, 0);
			if (ct == 0)
			{
				rs.rw.WrapResult = this.BeginReadBuffer(false, this.InnerReadToEnd, rs);
				return;
			}

			if (rs.se == null)
			{
				rs.vs.Append(rs.cs, 0, ct);
				rs.bp += this.InnerEncoding.GetByteCount(rs.cs, 0, ct);
			}
			else
			{

				rs.vs.Append(rs.cs, rs.nl, rs.ct);
				rs.bp += this.InnerEncoding.GetByteCount(rs.cs, rs.nl, rs.ct);
				for (var i = 0; i < ct; i++)
				{
					var ii = 0;
					for (; ii < rs.nl; ii++)
					{
						if (rs.cs[i] != rs.se[ii])
							break;
					}
					if (ii >= rs.nl)
					{
						i += rs.nl;
						this.BytePosition = rs.bp - this.InnerEncoding.GetByteCount(rs.cs, i, ct - i);
						rs.rw.Complete(rs.vs.ToString().Remove(rs.vs.Length - ct + i), null);
					}
				}
			}
			if (rs.ml >= 0 && rs.vs.Length >= rs.ml)
			{
				//this._BytePosition = bp;
				//rs.rw.Complete(rs.vs.ToString(), null);
				rs.rw.Complete(null, null);
				return;
			}

			rs.rw.WrapResult = this.BeginReadBuffer(false, this.InnerReadToEnd, rs);
		}

		/// <summary/>
		public string EndReadToEnd(IAsyncResult asyncResult)
		{
			var ar = asyncResult as IAsyncResultWrap;
			if (ar.WrapError != null)
				throw ar.WrapError;

			return (string)ar.WrapReturn;
		}

		/// <summary>
		/// 读取字符串，行尾带结束符，若为流结尾则不一定带结束符，如果超过最大数据则返回 Null
		/// </summary>
		/// <param name="max">返回最大字符数，小于零表示不限制</param>
		/// <param name="end">结束标识字符串</param>
		/// <returns>返字符串，行尾带结束符，若为流结尾则不一定带结束符，如果超过最大数据则返回 Null</returns>
		public string ReadToEnd(int max, string end)
		{
			if (string.IsNullOrEmpty(end))
				return this.ReadToEnd(max);

			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			if (max == 0)
				return string.Empty;

			var rs = new ReadState();
			rs.se = end;
			rs.nl = rs.se.Length;
			rs.vs = this.InnerBuffer;
			rs.bs = this.ByteBuffer;
			rs.ml = max;
			rs.bp = rs.ml > 0 ? (rs.ml > BitUtil.K ? BitUtil.K : rs.ml) : BitUtil.K;
			rs.cs = this.CharBuffer;
			if (rs.cs == null || rs.cs.Length < rs.bp)
				this.CharBuffer = rs.cs = new char[rs.bp];
			rs.bp = this.InnerEncoding.GetMaxByteCount(rs.cs.Length);
			if (rs.bp % BitUtil.K > 0)
				rs.bp = BitUtil.K * (rs.bp / BitUtil.K + 1);
			if (this.InnerBuffer == null)
				this.InnerBuffer = rs.vs = new StringBuilder();
			else
				this.InnerBuffer.Clear();
			if (rs.bp > this.ByteBuffer.Length - this.BytePosition)
			{
				this.ByteBuffer = new byte[rs.bp > this.ByteBuffer.Length ? rs.bp : this.ByteBuffer.Length];
				this.ByteLength -= this.BytePosition;
				Buffer.BlockCopy(rs.bs, this.BytePosition, this.ByteBuffer, 0, this.ByteLength);
				this.BytePosition = 0;
				rs.bs = this.ByteBuffer;
			}
			rs.bp = this.BytePosition;
			for (; ; )
			{
				if (this.ByteLength <= this.BytePosition && this.ReadBuffer() == 0)
				{
					this.BytePosition = rs.bp;
					this.Dispose();
					return rs.vs.ToString();
				}

				var ct = this.InnerEncoding.GetChars(rs.bs, rs.bp, this.ByteLength - rs.bp, rs.cs, rs.nl) + rs.nl;
				if (ct == rs.nl)
					continue;

				rs.vs.Append(rs.cs, rs.nl, rs.ct);
				rs.bp += this.InnerEncoding.GetByteCount(rs.cs, rs.nl, rs.ct);
				for (var i = 0; i < ct; i++)
				{
					var ii = 0;
					for (; ii < rs.nl; ii++)
					{
						if (rs.cs[i] != end[ii])
							break;
					}
					if (ii >= rs.nl)
					{
						i += rs.nl;
						this.BytePosition = rs.bp - this.InnerEncoding.GetByteCount(rs.cs, i, ct - i);
						return rs.vs.ToString().Remove(rs.vs.Length - ct + i);
					}
				}
				if (rs.ml >= 0 && rs.vs.Length >= rs.ml)
					break;
			}
			//this._BytePosition = bp;
			//return vs.ToString();
			return null;
		}

		/// <summary>
		/// 读取字符串，行尾带结束符，若为流结尾则不一定带结束符，如果超过最大数据则返回 Null
		/// </summary>
		/// <param name="max">返回最大字符数，小于零表示不限制</param>
		/// <param name="end">结束标识字符串</param>
		/// <param name="callback"></param>
		/// <param name="state"></param>
		/// <returns></returns>
		public IAsyncResult ReadToEnd(int max, string end, AsyncCallback callback, object state)
		{
			if (string.IsNullOrEmpty(end))
				return this.BeginReadToEnd(max, callback, state);

			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			if (max == 0)
				return AsyncResultWrap.SyncComplete(string.Empty, null, callback, state);

			var rs = new ReadState();
			rs.rw = new AsyncResultWrap(-1, callback, state);
			rs.se = end;
			rs.nl = rs.se.Length;
			rs.vs = this.InnerBuffer;
			rs.bs = this.ByteBuffer;
			rs.ml = max;
			rs.bp = rs.ml > 0 ? (rs.ml > BitUtil.K ? BitUtil.K : rs.ml) : BitUtil.K;
			rs.cs = this.CharBuffer;
			if (rs.cs == null || rs.cs.Length < rs.bp)
				this.CharBuffer = rs.cs = new char[rs.bp];
			rs.bp = this.InnerEncoding.GetMaxByteCount(rs.cs.Length);
			if (rs.bp % BitUtil.K > 0)
				rs.bp = BitUtil.K * (rs.bp / BitUtil.K + 1);
			if (this.InnerBuffer == null)
				this.InnerBuffer = rs.vs = new StringBuilder();
			else
				this.InnerBuffer.Clear();
			if (rs.bp > this.ByteBuffer.Length - this.BytePosition)
			{
				this.ByteBuffer = new byte[rs.bp > this.ByteBuffer.Length ? rs.bp : this.ByteBuffer.Length];
				this.ByteLength -= this.BytePosition;
				Buffer.BlockCopy(rs.bs, this.BytePosition, this.ByteBuffer, 0, this.ByteLength);
				this.BytePosition = 0;
				rs.bs = this.ByteBuffer;
			}
			rs.bp = this.BytePosition;
			if (this.BytePosition >= this.ByteLength)
				rs.rw.WrapResult = this.BeginReadBuffer(false, this.InnerReadToEnd, rs);
			else
				this.InnerReadToEnd(rs.rw);
			return rs.rw;
		}

		/// <summary/>
		public virtual Stream BaseStream
		{
			get
			{
				return this.InnerStream;
			}
		}

		/// <summary/>
		public virtual Encoding CurrentEncoding
		{
			get
			{
				return this.InnerEncoding;
			}
		}

		/// <summary/>
		public bool EndOfStream
		{
			get
			{
				if (this.InnerStream == null)
					return true;

				if (this.LastRead == 0)
					return true;

				return false;
			}
		}

		/// <summary/>
		public bool Disposed
		{
			get
			{
				if (this.InnerStream == null)
					return true;

				return false;
			}
		}

		#region Stream

		/// <summary/>
		public override bool CanRead
		{
			get
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				return this.InnerStream.CanRead;
			}
		}

		/// <summary/>
		public override bool CanSeek
		{
			get
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				return this.InnerStream.CanSeek;
			}
		}

		/// <summary/>
		public override bool CanTimeout
		{
			get
			{
				return this.InnerStream.CanTimeout;
			}
		}

		/// <summary/>
		public override bool CanWrite
		{
			get
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				return this.InnerStream.CanWrite;
			}
		}

		/// <summary/>
		public override void Flush()
		{
			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			this.InnerStream.Flush();
		}

		/// <summary/>
		public override long Length
		{
			get
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				return this.InnerStream.Length;
			}
		}

		/// <summary/>
		public override long Position
		{
			get
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				return this.InnerStream.Position - this.ByteLength + this.BytePosition;
			}
			set
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				this.InnerStream.Position = value;
				this.BytePosition = 0;
				this.ByteLength = 0;
			}
		}

		/// <summary/>
		public override int ReadTimeout
		{
			get
			{
				return this.InnerStream.ReadTimeout;
			}
			set
			{
				this.InnerStream.ReadTimeout = value;
			}
		}

		/// <summary/>
		public override int WriteTimeout
		{
			get
			{
				return this.InnerStream.WriteTimeout;
			}
			set
			{
				this.InnerStream.WriteTimeout = value;
			}
		}

		/// <summary/>
		public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
		{
			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			if (this.ByteLength > this.BytePosition)
			{
				if (count > this.ByteLength - this.BytePosition)
					count = this.ByteLength - this.BytePosition;
				Buffer.BlockCopy(this.ByteBuffer, this.BytePosition, buffer, offset, count);
				this.BytePosition += count;
				return AsyncResultWrap.SyncComplete(count, null, callback, state);
			}

			var ar = new AsyncResultWrap(1,  callback, state);
			try
			{
				ar.WrapResult = this.InnerStream.BeginRead(buffer, offset, count, this.InnerRead, ar);
			}
			catch (Exception x)
			{
				return ar.Complete(x);
			}

			return ar;
		}

		/// <summary/>
		public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
		{
			if (this.ByteLength > this.BytePosition)
				this.Seek(this.BytePosition - this.ByteLength, SeekOrigin.Current);
			try
			{
				var ar = new AsyncResultWrap(1, callback, state);
				ar.WrapResult = this.InnerStream.BeginWrite(buffer, offset, count, this.InnerWrite, ar);
				return ar;
			}
			catch
			{
				if (this.ByteLength > this.BytePosition)
					this.Seek(this.ByteLength - this.BytePosition, SeekOrigin.Current);
				throw;
			}
		}

		/// <summary/>
		public override void Close()
		{
			this.Dispose();
		}

		private void InnerRead(IAsyncResult asyncResult)
		{
			var ar = asyncResult.AsyncState as AsyncResultWrap;
			ar.WrapResult = asyncResult;
			try
			{
				this.LastRead = this.InnerStream.EndRead(ar.WrapResult);
				this.BytePosition = 0;
				this.ByteLength = 0;
				ar.WrapReturn = this.LastRead;
				ar.Complete(this.LastRead, null);
			}
			catch (Exception x)
			{
				ar.Complete(x);
			}
		}

		/// <summary/>
		public override int EndRead(IAsyncResult asyncResult)
		{
			var ar = asyncResult as IAsyncResultWrap;
			if (ar.WrapError != null)
				throw ar.WrapError;

			return (int)ar.WrapReturn;
		}

		private void InnerWrite(IAsyncResult result)
		{
			var ar = result.AsyncState as AsyncResultWrap;
			ar.WrapResult = result;
			try
			{
				this.InnerStream.EndWrite(result);
				if (this.InnerStream.Length > this.InnerStream.Position)
					this.LastRead = 1;
				this.BytePosition = 0;
				this.ByteLength = 0;
				ar.Complete();
			}
			catch (Exception x)
			{
				if (this.ByteLength > this.BytePosition)
					this.Seek(this.ByteLength - this.BytePosition, SeekOrigin.Current);
				ar.Complete(x);
			}
		}

		/// <summary/>
		public override void EndWrite(IAsyncResult asyncResult)
		{
			var ar = asyncResult as IAsyncResultWrap;
			if (ar.WrapError != null)
				throw ar.WrapError;
		}

		public int Read(byte[] buffer)
		{
			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			if (buffer == null)
				return 0;

			return this.Read(buffer, 0, buffer.Length);
		}

		/// <summary/>
		public override int Read(byte[] buffer, int offset, int count)
		{
			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			if (buffer == null)
				return 0;

			if (this.ByteLength > this.BytePosition)
			{
				if (count > this.ByteLength - this.BytePosition)
					count = this.ByteLength - this.BytePosition;
				Buffer.BlockCopy(this.ByteBuffer, this.BytePosition, buffer, offset, count);
				this.BytePosition += count;
				return count;
			}

			this.LastRead = this.InnerStream.Read(buffer, offset, count);
			this.BytePosition = 0;
			this.ByteLength = 0;
			return this.LastRead;
		}

		/// <summary/>
		public override int ReadByte()
		{
			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			if (this.ByteLength > this.BytePosition)
			{
				this.BytePosition++;
				return this.ByteBuffer[this.BytePosition];
			}

			var i = this.InnerStream.ReadByte();
			this.BytePosition = 0;
			this.ByteLength = 0;
			if (i >= 0)
				this.LastRead = 1;
			else
				this.LastRead = 0;
			return i;
		}

		/// <summary/>
		public override long Seek(long offset, SeekOrigin origin)
		{
			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			var i = this.InnerStream.Seek(offset, origin);
			this.BytePosition = 0;
			this.ByteLength = 0;
			if (this.InnerStream.Length == i)
				this.LastRead = 0;
			return i;
		}

		/// <summary/>
		public override void SetLength(long value)
		{
			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			var p = this.InnerStream.Position;
			this.InnerStream.SetLength(value);
			p = value - p;
			if (p >= 0L)
			{
				this.LastRead = this.ByteLength - this.BytePosition;
				return;
			}

			this.ByteLength = (int)(this.ByteLength + p);
			this.LastRead = this.ByteLength - this.BytePosition;
			if (this.LastRead > 0)
				return;

			this.BytePosition = 0;
			this.ByteLength = 0;
		}

		/// <summary/>
		public void Write(byte[] buffer)
		{
			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			if (buffer == null)
				return;

			this.Write(buffer, 0, buffer.Length);
		}

		/// <summary/>
		public override void Write(byte[] buffer, int offset, int count)
		{
			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			if (buffer == null)
				return;

			if (this.ByteLength > this.BytePosition)
				this.Seek(this.BytePosition - this.ByteLength, SeekOrigin.Current);
			try
			{
				this.InnerStream.Write(buffer, offset, count);
			}
			catch
			{
				if (this.ByteLength > this.BytePosition)
					this.Seek(this.ByteLength - this.BytePosition, SeekOrigin.Current);
				throw;
			}

			if (this.InnerStream.Length > this.InnerStream.Position)
				this.LastRead = 1;
			this.BytePosition = 0;
			this.ByteLength = 0;
		}

		/// <summary/>
		public override void WriteByte(byte value)
		{
			if (this.InnerStream == null)
				throw new ObjectDisposedException(this.GetType().Name);

			if (this.ByteLength > this.BytePosition)
				this.Seek(this.BytePosition - this.ByteLength, SeekOrigin.Current);
			try
			{
				this.InnerStream.WriteByte(value);
			}
			catch
			{
				if (this.ByteLength > this.BytePosition)
					this.Seek(this.ByteLength - this.BytePosition, SeekOrigin.Current);
				throw;
			}

			if (this.InnerStream.Length > this.InnerStream.Position)
				this.LastRead = 1;
			this.BytePosition = 0;
			this.ByteLength = 0;
		}

		#endregion
	}

}
